#享元模式

#一、享元模式的优点和使用场景
#优点：
#1、减少重复对象，大大节约了系统资源。

#使用场景：
#1、系统中存在大量的相似对象时，可以选择享元模式提高资源利用率。咖啡订购平台比较小，若假设一个电商平台，每个买家和卖家建立起买卖关系后，买家对象和卖家对象都是占用资源的。如果一个卖家同时与多个买家建立起买卖关系呢？此时享元模式的优势就体现出来了；2、需要缓冲池的场景中，可以使用享元模式。如进程池，线程池等技术，就可以使用享元模式（事实上，很多的池技术中已经使得了享元模式）。

#二、享元模式的缺点
#1、享元模式虽然节约了系统资源，但同时也提高了系统的复杂性，尤其当遇到外部状态和内部状态混在一起时，需要先将其进行分离，才可以使用享元模式。否则，会引起逻辑混乱或业务风险；2、享元模式中需要额外注意线程安全问题。

#定义享元接口
class TreeType:
    def __init__(self, name, color, texture):
        self.name = name
        self.color = color
        self.texture = texture

    def draw(self, canvas, x, y):
        print(f"在({x}, {y})位置，画一个{self.color}颜色的{self.name}，纹理是{self.texture}。")

#创建享元工厂
class TreeFactory:
    _tree_types = {}

    @staticmethod
    def get_tree_type(name, color, texture):
        key = (name, color, texture)
        if not TreeFactory._tree_types.get(key):
            print("创建一个新的TreeType。")
            TreeFactory._tree_types[key] = TreeType(name, color, texture)
        else:
            print("复用已有的TreeType。")
        return TreeFactory._tree_types[key]

#使用享元对象
class Tree:
    def __init__(self, x, y, name, color, texture):
        self.x = x
        self.y = y
        self.tree_type = TreeFactory.get_tree_type(name, color, texture)

    def draw(self, canvas):
        self.tree_type.draw(canvas, self.x, self.y)


class Forest:
    def __init__(self):
        self.trees = []

    def plant_tree(self, x, y, name, color, texture):
        tree = Tree(x, y, name, color, texture)
        self.trees.append(tree)

    def draw(self, canvas):
        for tree in self.trees:
            tree.draw(canvas)


if __name__ == "__main__":
    forest = Forest()
    forest.plant_tree(1, 2, "松树", "绿色", "粗糙")
    forest.plant_tree(2, 3, "松树", "绿色", "粗糙")
    forest.plant_tree(3, 5, "橡树", "棕色", "平滑")
    forest.draw("画布")
